/**
 *	@file	np_main.c
 *	@brief	木の実プランターアプリメイン
 *	@author	Miyuki Iwasawa
 *	@date	08.08.04
 *
 */

#include "common.h"
#include "system/procsys.h"
#include "system/bmp_list.h"
#include "system/bmp_menu.h"
#include "system/arc_util.h"
#include "system/arc_tool.h"
#include "system/snd_tool.h"
#include "system/fontproc.h"
#include "system/pm_str.h"
#include "system/msgdata.h"
#include "system/buflen.h"
#include "system/window.h"
#include "system/brightness.h"
#include "system/clact_util.h"
#include "system/clact_tool.h"
#include "system/render_oam.h"
#include "system/palanm.h"
#include "system/wipe.h"
#include "system/window.h"
#include "system/font_arc.h"
#include "system/winframe.naix"
#include "gflib/touchpanel.h"
#include "itemtool/myitem.h"
#include "itemtool/item.h"
#include "msgdata/msg.naix"

#include "savedata/config.h"
#include "application/nut_planter.h"
#include "np_sys.h"
#include "np_tool.h"
#include "np_app.h"
#include "np_sub.h"
#include "np_time.h"
#include "np_key.h"
#include "np_snd_def.h"
#include "nuts.h"

#ifdef DEBUG_ONLY_FOR_iwasawa
 #undef IWASAWA_PRINT
 #define IWASAWA_PRINT(...) ((void) 0)
#endif

//=========================================================
//プロトタイプ定義
//=========================================================
static void app_InitData(NP_APPWORK* wk);
static void app_EndData(NP_APPWORK* wk);
static BOOL app_Init(NP_APPWORK* wk);
static BOOL app_End(NP_APPWORK* wk);


static int seq_FadeIn(NP_APPWORK* wk);
static int seq_FadeOut(NP_APPWORK* wk);
static int seq_BedSelect(NP_APPWORK* wk);
static int seq_ListCompost(NP_APPWORK* wk);
static int seq_ListPlant(NP_APPWORK* wk);
static int seq_ListWater(NP_APPWORK* wk);
static int seq_ListHarvest(NP_APPWORK* wk);
static int seq_PlantMsgWait(NP_APPWORK* wk);
static int seq_MsgWait(NP_APPWORK* wk);

static void sub_BedStatusUpdate(NP_APPWORK* wk);
static int sub_CheckNextSeq(NP_APPWORK* wk);
static BOOL sub_MsgWait(NP_APPWORK* wk);

//=========================================================
//プロセス定義
//=========================================================
/**
 *	@brief	木の実プランターアプリ呼び出し
 */
PROC_RESULT NPlanterProc_Init(PROC* proc,int* seq)
{

	switch(*seq){
	case 0:
		NPTool_ViewClear();

		//ヒープ作成
		HeapStatePush();
		sys_CreateHeap(HEAPID_BASE_APP,HEAPID_NPLANTER_APP,0x20000);

		{
			NP_APPWORK* wk = NULL;
			wk = PROC_AllocWork(proc,sizeof(NP_APPWORK),HEAPID_NPLANTER_APP);
			MI_CpuClear8(wk,sizeof(NP_APPWORK));

			wk->heapID = HEAPID_NPLANTER_APP;
			wk->sp = (NP_SYSWORK*)PROC_GetParentWork(proc);

			//引継ぎデータ初期化
			app_InitData(wk);

		}
		(*seq)++;
		break;
	case 1:
		if(app_Init((NP_APPWORK*)PROC_GetWork(proc))){
			return PROC_RES_FINISH;
		}
	}
	return PROC_RES_CONTINUE;
}

/**
 *	@brief	木の実プランターモジュールメイン
 */
PROC_RESULT NPlanterProc_Main(PROC* proc,int* seq)
{
	NP_APPWORK* wk = (NP_APPWORK*)PROC_GetWork(proc);

	switch(*seq){
	case SEQ_FADE_IN:
		*seq = seq_FadeIn(wk);
		break;
	case SEQ_FADE_OUT:
		*seq = seq_FadeOut(wk);
		break;
	case SEQ_BED_SELECT:
		*seq = seq_BedSelect(wk);
		break;
	case SEQ_LIST_COMPOST:
		*seq = seq_ListCompost(wk);
		break;
	case SEQ_LIST_PLANT:
		*seq = seq_ListPlant(wk);
		break;
	case SEQ_LIST_WATER:
		*seq = seq_ListWater(wk);
		break;
	case SEQ_LIST_HARVEST:
		*seq = seq_ListHarvest(wk);
		break;
	case SEQ_PLANT_MSG_WAIT:
		*seq = seq_PlantMsgWait(wk);
		break;
	case SEQ_MSG_WAIT:
		*seq = seq_MsgWait(wk);
		break;
	case SEQ_EXIT:
		return PROC_RES_FINISH;
	}
	CATS_Draw(wk->pActRes);
	return PROC_RES_CONTINUE;
}

/**
 *	@brief	木の実プランターモジュール終了
 */
PROC_RESULT NPlanterProc_End(PROC* proc,int* seq)
{
	NP_APPWORK* wk = (NP_APPWORK*)PROC_GetWork(proc);

	if(!app_End(wk)){
		return PROC_RES_CONTINUE;
	}
//	an_puzzle_ViewClear();

	//引継ぎデータ書き戻し
	app_EndData(wk);

	//ワーク解放
	PROC_FreeWork(proc);

	HeapStatePop();
	HeapStateCheck(HEAPID_NPLANTER_APP);

	sys_DeleteHeap(HEAPID_NPLANTER_APP);

	return PROC_RES_FINISH;
}

////////////////////////////////////////////////////////////////////////
//サブ

/**
 *	@brief	引継ぎデータ初期化
 */
static void app_InitData(NP_APPWORK* wk)
{
	int i;
	CONFIG* config;

	//キーモード初期化
	wk->key_mode = KeyTouchStatus_CheckTouchOrKey(wk->sp->param->kt_status);

	//コンフィグ
	config = SaveData_GetConfig(wk->sp->param->save);
	wk->msg_spd = CONFIG_GetMsgPrintSpeed(config);
	wk->win_type = CONFIG_GetWindowType(config);

	//アイテムデータ
	wk->item_sv = SaveData_GetMyItem(wk->sp->param->save);
	//レコードデータ
	wk->rec_sv = SaveData_GetRecord(wk->sp->param->save);

	//ベッドときのみ時間、パラメータを取得
	wk->seed_prm = SEEDBED_CreateParamTable(wk->heapID);
	wk->seed_bed = SaveData_GetSeedBed(wk->sp->param->save);
	wk->seed_time = SaveData_GetSeedTime(wk->sp->param->save);

	//カーソル位置復帰
	if(wk->sp->mode != SYSMODE_NORMAL){
		wk->c_pos = wk->sp->ret_target;
	}else{
		wk->c_pos = 0;
	}

	//ベッドの状態をアップデート
	sub_BedStatusUpdate(wk);

	//今持っている木の実の総数とこやしの総数を数えておく
	wk->item_num_seed = SeedSys_GetItemNutsNumAll(wk->item_sv,wk->heapID);
	wk->item_num_compost = SeedSys_GetItemCompostNumAll(wk->item_sv,wk->heapID);

	//状態ワークをアップデート
	NPTime_SeedStateUpdate( wk );
}

/**
 *	@brief	引継ぎデータ終了処理
 */
static void app_EndData(NP_APPWORK* wk)
{
	//きのみパラメータ解放
	sys_FreeMemoryEz(wk->seed_prm);

	//キーモード書き戻し
	KeyTouchStatus_SetTouchOrKey(wk->sp->param->kt_status,wk->key_mode);

#ifdef PM_DEBUG
	//時間促進強制リセット
	DEBUG_StopFakeTime();
#endif
}

/**
 *	@brief	初期化
 *
 */
static BOOL app_Init(NP_APPWORK* wk)
{
	switch(wk->seq){
	case 0:
		NPlanterResInit(wk);
		++wk->seq;
		break;
	case 1:
		NPlanterInitialDraw(wk);

		//タッチパネル初期化
		InitTPSystem();
		InitTPNoBuff(1);

		Snd_DataSetByScene( SND_SCENE_SUB_PLANTER, 0, 0 );
		wk->seq = 0;
		return TRUE;
	}
	return FALSE;

}

/**
 *	@brief	終了処理
 *
 */
static BOOL app_End(NP_APPWORK* wk)
{
	//タッチパネル終了
	StopTP();

	NPlanterResRelease(wk);
	return TRUE;
}

/**
 *	@brief	フェードイン
 *
 */
static int seq_FadeIn(NP_APPWORK* wk)
{
	switch(wk->seq){
	case 0:
		WIPE_SYS_Start(
			WIPE_PATTERN_WMS, WIPE_TYPE_FADEIN,
			WIPE_TYPE_FADEIN, WIPE_FADE_BLACK, WIPE_DEF_DIV, WIPE_DEF_SYNC, wk->heapID);
		wk->seq++;
		break;
	case 1:
		if( !WIPE_SYS_EndCheck()){
			break;
		}
		wk->seq = 0;
		return sub_CheckNextSeq( wk );
	}
	return SEQ_FADE_IN;
}

/**
 *	@brief	フェードアウト
 *
 */
static int seq_FadeOut(NP_APPWORK* wk)
{
	switch(wk->seq){
	case 0:
		WIPE_SYS_Start(
			WIPE_PATTERN_WMS, WIPE_TYPE_FADEOUT,
			WIPE_TYPE_FADEOUT, WIPE_FADE_BLACK, WIPE_DEF_DIV, WIPE_DEF_SYNC, wk->heapID);
		wk->seq++;
		break;
	case 1:
		if( !WIPE_SYS_EndCheck()){
			break;
		}
		wk->seq = 0;
		return SEQ_EXIT;
	}
	return SEQ_FADE_OUT;
}

/**
 *	@brief	ベッド選択
 */
static int seq_BedSelect(NP_APPWORK* wk)
{
	int ret;

	ret = NPKey_InputBedSelect(wk);

	if(ret == SEQ_BED_SELECT){
		NPTime_Update( wk , TRUE );
	}
	return ret;
}

/**
 *	@brief	(きのみ＆こやしを)蒔くリスト
 */
static int seq_ListCompost(NP_APPWORK* wk)
{
	u32 ret;

	switch(wk->seq){
	case 0:
		NPSub_SBoxSet( wk, NP_SBOX_COMPOST );
		NPSub_MsgPut(wk,MIDX_BS_EMPTY,wk->c_pos,TRUE);
		NPSub_ActAnmControl(wk,FALSE);
		wk->seq++;
		break;
	case 1:
		ret = NPSub_SBoxWait( wk );
		if(ret == SBOX_SELECT_NULL ){
			break;
		}
		wk->seq = 0;

		if(ret == 2 || ret == SBOX_SELECT_CANCEL){
			NPSub_MsgPut(wk,MIDX_BED_SELECT,BED_NULL,TRUE);
			NPSub_ActAnmControl(wk,TRUE);
			return SEQ_BED_SELECT;
		}
		wk->sp->ret_target = wk->c_pos;
		wk->sp->ret_item = 0xFFFF;

		if(ret == 0){
			if(wk->item_num_compost == 0){
				NPSub_MsgPut(wk,MIDX_COMPOST_NONE,BED_NULL,FALSE);
				return SEQ_MSG_WAIT;
			}
			wk->sp->mode = SYSMODE_COMPOST;
		}else{
			if(wk->item_num_seed == 0){
				NPSub_MsgPut(wk,MIDX_SEED_NONE,BED_NULL,FALSE);
				return SEQ_MSG_WAIT;
			}
			wk->sp->mode = SYSMODE_SEED;
		}
		return SEQ_FADE_OUT;
	}
	return SEQ_LIST_COMPOST;
}

/**
 *	@brief	きのみを蒔くリスト
 */
static int seq_ListPlant(NP_APPWORK* wk)
{
	u32 ret;

	switch(wk->seq){
	case 0:
		NPSub_SBoxSet( wk, NP_SBOX_PLANT );
		NPSub_MsgPut(wk,MIDX_BS_COMPOST,wk->c_pos,TRUE);
		NPSub_ActAnmControl(wk,FALSE);
		wk->seq++;
		break;
	case 1:
		ret = NPSub_SBoxWait( wk );
		if(ret == SBOX_SELECT_NULL ){
			break;
		}
		wk->seq = 0;

		if(ret == 1 || ret == SBOX_SELECT_CANCEL){
			NPSub_MsgPut(wk,MIDX_BED_SELECT,BED_NULL,TRUE);
			NPSub_ActAnmControl(wk,TRUE);
			return SEQ_BED_SELECT;
		}
		if(wk->item_num_seed == 0){
			NPSub_MsgPut(wk,MIDX_SEED_NONE,BED_NULL,FALSE);
			return SEQ_MSG_WAIT;
		}
		wk->sp->ret_target = wk->c_pos;
		wk->sp->ret_item = 0xFFFF;
		wk->sp->mode = SYSMODE_SEED;
		return SEQ_FADE_OUT;
	}
	return SEQ_LIST_PLANT;
}

/**
 *	@brief	水を蒔くリスト
 */
static int seq_ListWater(NP_APPWORK* wk)
{
	u32 ret;

	switch(wk->seq){
	case 0:
		NPSub_SBoxSet( wk, NP_SBOX_WATER );
		NPSub_ActAnmControl(wk,FALSE);
		NPSub_MsgPut(wk,MIDX_BS_GROWS01+(wk->seed[wk->c_pos].stat-SEEDSTAT_UNDERGROUND),wk->c_pos,TRUE);
		wk->seq++;
		break;
	case 1:
		ret = NPSub_SBoxWait( wk );
		if( ret == SBOX_SELECT_NULL ){
			break;
		}
		if(ret == 1 || ret == SBOX_SELECT_CANCEL ){
			wk->seq = 0;
			NPSub_MsgPut(wk,MIDX_BED_SELECT,BED_NULL,TRUE);
			NPSub_ActAnmControl(wk,TRUE);
			return SEQ_BED_SELECT;
		}
		NPSub_MsgPut(wk,MIDX_WATER_KEY,BED_NULL,FALSE);
		wk->seq++;
		break;
	case 2:
		if(!NPSubSeq_WaterEffect(wk)){
			break;
		}
		NPSub_MsgPut(wk,MIDX_RA_WATER,BED_NULL,FALSE);
		wk->seq++;
	default:
		if(!sub_MsgWait(wk)){
			break;
		}
		NPSub_CursorPosSet(wk);
		NPSub_ActAnmControl(wk,TRUE);
		NPSub_MsgPut(wk,MIDX_BED_SELECT,BED_NULL,TRUE);
		wk->seq = 0;
		return SEQ_BED_SELECT;
	}
	return SEQ_LIST_WATER;
}

/**
 *	@brief	収穫するリスト
 */
static int seq_ListHarvest(NP_APPWORK* wk)
{
	u32 ret;

	switch(wk->seq){
	case 0:
		NPSub_SBoxSet( wk, NP_SBOX_HARVEST );
		NPSub_MsgPut(wk,MIDX_BS_GROWS05,wk->c_pos,TRUE);
		NPSub_ActAnmControl(wk,FALSE);
		wk->seq++;
		break;
	case 1:
		ret = NPSub_SBoxWait( wk );
		if(ret == SBOX_SELECT_NULL ){
			break;
		}
		if(ret == 1 || ret == SBOX_SELECT_CANCEL){
			wk->seq = 0;
			NPSub_MsgPut(wk,MIDX_BED_SELECT,BED_NULL,TRUE);
			NPSub_ActAnmControl(wk,TRUE);
			return SEQ_BED_SELECT;
		}
		//収穫できるかチェック
		{
			SEED_STATE* st = &wk->seed[wk->c_pos];

			if(MyItem_AddCheck( wk->item_sv, SeedSys_Nuts2Item(st->type), st->nuts_ct, wk->heapID )){
				wk->seq = 3;
				NPSub_CursorVisibleSet(wk,FALSE);
				break;
			}
			//バッグがいっぱいだ
			NPSub_MsgPut(wk,MIDX_RA_HARVEST03,wk->c_pos,FALSE);
		}
		wk->seq++;
		break;
	case 2:
		//収穫できなかったメッセージ表示待ち
		if(!sub_MsgWait(wk)){
			break;
		}
		wk->seq = 0;
		NPSub_MsgPut(wk,MIDX_BED_SELECT,BED_NULL,TRUE);
		NPSub_ActAnmControl(wk,TRUE);
		return SEQ_BED_SELECT;

	case 3:
		//収穫エフェクト
		if(!NPSubSeq_HarvestEffect(wk)){
			break;
		}
		//○のみを○ことった！
		NPSub_MsgPut(wk,MIDX_RA_HARVEST01,wk->c_pos,FALSE);
		//木の実取得ジングル
		Snd_MePlay( SEQ_ME_KINOMI );
		wk->seq++;
		break;
	case 4:
		//ジングル待ち
		if(Snd_MePlayCheckBgmPlay()){
			break;
		}
		NPSub_MsgPut(wk,MIDX_RA_HARVEST02,wk->c_pos,FALSE);
		wk->seq++;
	case 5:
		if(!sub_MsgWait(wk)){
			break;
		}
		//収穫
		NPSub_Harvest(wk);
		#ifdef PM_DEBUG
		 Deb_SeedPrint( wk );
		#endif	//PM_DEBUG

		NPSub_CursorPosSet(wk);
		NPSub_ActAnmControl(wk,TRUE);
		NPSub_CursorVisibleSet(wk,TRUE);
		NPSub_MsgPut(wk,MIDX_BED_SELECT,BED_NULL,TRUE);
		wk->seq = 0;
		return SEQ_BED_SELECT;
	}
	return SEQ_LIST_HARVEST;
}

/**
 *	@brief 木の実＆肥やし追加　SE再生＆メッセージ待ち
 */
static int seq_PlantMsgWait(NP_APPWORK* wk)
{
	switch(wk->seq){
	case 0:
		Snd_SePlay(SND_NP_PLANT);
		wk->seq++;
		break;
	case 1:
		if(!sub_MsgWait(wk)){
			break;
		}
		NPSub_MsgPut(wk,MIDX_BED_SELECT,BED_NULL,TRUE);
		NPSub_ActAnmControl(wk,TRUE);
		wk->seq = 0;
		return SEQ_BED_SELECT;
	}
	return SEQ_PLANT_MSG_WAIT;
}

/**
 *	@brief 書き切りメッセージ待ち
 */
static int seq_MsgWait(NP_APPWORK* wk)
{
	if(sub_MsgWait(wk)){
		NPSub_MsgPut(wk,MIDX_BED_SELECT,BED_NULL,TRUE);
		NPSub_ActAnmControl(wk,TRUE);
		return SEQ_BED_SELECT;
	}
	return SEQ_MSG_WAIT;
}

/**
 *	@brief	選ばれたアイテムが肥やしかどうかチェック
 */
static BOOL sub_IsCompostItem(u16 itemno)
{
	if(	itemno < COMPOST_START_ITEMNUM ||
		itemno > (COMPOST_START_ITEMNUM+ITEM_COMPOST_MAX)){
		return FALSE;
	}
	return TRUE;
}

/**
 *	@brief	道具画面復帰後のベッドステータス更新
 */
static void sub_BedStatusUpdate(NP_APPWORK* wk)
{
	wk->ret_mode = 0;
	if(	wk->sp->mode == SYSMODE_NORMAL ||
		wk->sp->ret_item == 0xFFFF){
		return;	//なにもしない
	}

	if(wk->sp->mode == SYSMODE_COMPOST){
		//選ばれた道具がこやしかどうかチェック
		if(!sub_IsCompostItem(wk->sp->ret_item)){
			return;
		}
		//肥料データをセット
		SEEDBED_SetCompost(wk->seed_bed, wk->c_pos, SeedSys_Item2Compost(wk->sp->ret_item) );
		IWASAWA_PRINT("こやしセット %d -> %d\n",wk->c_pos,SeedSys_Item2Compost(wk->sp->ret_item));
		wk->ret_mode = 1;
	}else if(wk->sp->mode == SYSMODE_SEED){
		//選ばれた道具が木の実かどうかチェック
		if(!ItemNutsCheck(wk->sp->ret_item)){
			return;
		}
		SEEDBED_SetNuts(wk->seed_bed, wk->c_pos, wk->seed_prm, SeedSys_Item2Nuts(wk->sp->ret_item));
		RECORD_Inc(wk->rec_sv, RECID_NUTS_PLANT );
		IWASAWA_PRINT("木の実セット %d -> %d\n",wk->c_pos,SeedSys_Item2Nuts(wk->sp->rEet_item));
		wk->ret_mode = 2;
	}
	//使ったアイテムを一個減らす
	MyItem_SubItem( wk->item_sv , wk->sp->ret_item , 1, wk->heapID );

}

/**
 *	@brief	道具画面復帰後の分岐チェック
 */
static int sub_CheckNextSeq(NP_APPWORK* wk)
{
	u8 mode = wk->sp->mode;

	wk->sp->mode = SYSMODE_NORMAL;	//モードリセット

	if(mode == SYSMODE_NORMAL){
		return SEQ_BED_SELECT;
	}
	if(wk->ret_mode != 0){
		return SEQ_PLANT_MSG_WAIT;
	}
	return SEQ_BED_SELECT;
}

/**
 *	@brief	メッセージ待ちサブ
 */
static BOOL sub_MsgWait(NP_APPWORK* wk)
{
	if( GF_TP_GetTrg()){
		Snd_SePlay( SND_NP_SELECT );
		wk->key_mode = APP_KTST_TOUCH;
		return TRUE;
	}
	if(sys.trg & PAD_BUTTON_KTST_CHG){
		wk->key_mode = APP_KTST_KEY;
	}
	if(sys.trg & (PAD_BUTTON_DECIDE|PAD_BUTTON_CANCEL)){
		Snd_SePlay( SND_NP_SELECT );
		return TRUE;
	}
	if(wk->msg_wait-- <= 0){
		Snd_SePlay( SND_NP_SELECT );
		return TRUE;
	}
	return FALSE;
}